# Что такое мьютекс?
# Механизм синхронизации доступа к общим ресурсам
##############################################
#Что контролирует мьютекс?
#Доступ к общим ресурсам
###################
#Что происходит, когда задача пытается захватить уже заблокированный мьютекс?
#Задача ожидает, пока мьютекс не будет освобожден.
########################################
# Как правильно освободить мьютекс?
# lock.release()
##############################################
#Какой метод используется для захвата мьютекса?
#lock.acquire()
#Чего позволяет избежать "мьютекс"?
#состояние гонки
#############################################
#Что такое "критическая секция" в контексте мьютексов?
#Участок кода, который может быть выполнен только одной задачей в любой момент времени.
########################################################
#Какой из перечисленных ресурсов НЕ требует синхронизации с помощью мьютекса?
#Локальные переменные внутри функции.
#############################
#Как будут выполняться задачи?
# import asyncio

# async def task(lock, name):
#     print(f"{name} пытается захватить мьютекс.")
#     async with lock:
#         print(f"{name} начал выполнение.")
#         await asyncio.sleep(1)
#     print(f"{name} завершил выполнение.")

# async def main():
#     lock = asyncio.Lock()
#     tasks = [task(lock, f"Task {i}") for i in range(1, 4)]
#     await asyncio.gather(*tasks)

# asyncio.run(main())
#Примечание: Мьютекс гарантирует, что доступ к критической секции кода будет предоставлен строго поочередно, даже в асинхронной среде выполнения.
###############################
#Что произойдет при возникновении исключения в "Task 1"?
import asyncio

async def task(lock, name):
    try:
        await lock.acquire()
        print(f"{name} захватил мьютекс.")
        await asyncio.sleep(1)
        if name == "Task 1":
            raise Exception("Ошибка в задаче 1")
    finally:
        lock.release()
        print(f"{name} освободил мьютекс.")

async def main():
    lock = asyncio.Lock()
    await asyncio.gather(task(lock, "Task 1"), task(lock, "Task 2"), return_exceptions=True)

asyncio.run(main())
